home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Ebooks / Thinking in C++ V2 / C25 / ShapeFactory2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  2.7 KB  |  113 lines

  1. //: C25:ShapeFactory2.cpp
  2. // From Thinking in C++, 2nd Edition
  3. // Available at http://www.BruceEckel.com
  4. // (c) Bruce Eckel 1999
  5. // Copyright notice in Copyright.txt
  6. // Polymorphic factory methods
  7. #include "../purge.h"
  8. #include <iostream>
  9. #include <string>
  10. #include <exception>
  11. #include <vector>
  12. #include <map>
  13. using namespace std;
  14.  
  15. class Shape {
  16. public:
  17.   virtual void draw() = 0;
  18.   virtual void erase() = 0;
  19.   virtual ~Shape() {}
  20. };
  21.  
  22. class ShapeFactory {
  23.   virtual Shape* create() = 0;
  24.   static map<string, ShapeFactory*> factories;
  25. public:
  26.   virtual ~ShapeFactory() {}
  27.   friend class ShapeFactoryInizializer;
  28.   class BadShapeCreation : public exception {
  29.     string reason;
  30.   public:
  31.     BadShapeCreation(string type) {
  32.       reason = "Cannot create type " + type;
  33.     }
  34.     const char *what() const { 
  35.       return reason.c_str(); 
  36.     }
  37.   };
  38.   static Shape* 
  39.   createShape(string id) throw(BadShapeCreation){
  40.     if(factories.find(id) != factories.end())
  41.       return factories[id]->create();
  42.     else
  43.       throw BadShapeCreation(id);
  44.   }
  45. };
  46.  
  47. // Define the static object:
  48. map<string, ShapeFactory*> 
  49.   ShapeFactory::factories;
  50.  
  51. class Circle : public Shape {
  52.   Circle() {} // Private constructor
  53. public:
  54.   void draw() { cout << "Circle::draw\n"; }
  55.   void erase() { cout << "Circle::erase\n"; }
  56.   ~Circle() { cout << "Circle::~Circle\n"; }
  57.   class Factory;
  58.   friend class Factory;
  59.   class Factory : public ShapeFactory {
  60.   public:
  61.     Shape* create() { return new Circle; }
  62.   };
  63. };
  64.  
  65. class Square : public Shape {
  66.   Square() {}
  67. public:
  68.   void draw() { cout << "Square::draw\n"; }
  69.   void erase() { cout << "Square::erase\n"; }
  70.   ~Square() { cout << "Square::~Square\n"; }
  71.   class Factory;
  72.   friend class Factory;
  73.   class Factory : public ShapeFactory {
  74.   public:
  75.     Shape* create() { return new Square; }
  76.   };
  77. };
  78.  
  79. // Singleton to initialize the ShapeFactory:
  80. class ShapeFactoryInizializer {
  81.   static ShapeFactoryInizializer si;
  82.   ShapeFactoryInizializer() {
  83.     ShapeFactory::factories["Circle"] =
  84.       new Circle::Factory;
  85.     ShapeFactory::factories["Square"] =
  86.       new Square::Factory;
  87.   }
  88. };
  89.  
  90. // Static member definition:
  91. ShapeFactoryInizializer
  92.   ShapeFactoryInizializer::si;
  93.  
  94. char* shlist[] = { "Circle", "Square", "Square",
  95.   "Circle", "Circle", "Circle", "Square", "" };
  96.  
  97. int main() {
  98.   vector<Shape*> shapes;
  99.   try {
  100.     for(char** cp = shlist; **cp; cp++)
  101.       shapes.push_back(
  102.         ShapeFactory::createShape(*cp));
  103.   } catch(ShapeFactory::BadShapeCreation e) {
  104.     cout << e.what() << endl;
  105.     return 1;
  106.   }
  107.   for(int i = 0; i < shapes.size(); i++) {
  108.     shapes[i]->draw();
  109.     shapes[i]->erase();
  110.   }
  111.   purge(shapes);
  112. } ///:~
  113.